package com.five.esearch.impl;
import com.alibaba.fastjson.JSON;
import com.five.dto.NovelEsDTO;
import com.five.esearch.INovelSearchService;
import com.five.query.NovelSearchQuery;
import com.five.result.Result;
import com.five.util.NovelIndexInitializer;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 小说搜索服务（基于Elasticsearch）
 */
@Service
public class NovelSearchServiceImpl implements INovelSearchService {

    private final RestHighLevelClient esClient;

    @Autowired
    public NovelSearchServiceImpl(RestHighLevelClient esClient) {

        this.esClient = esClient;
    }

    /**
     * 执行小说搜索
     */
    public Result<List<NovelEsDTO>> search(NovelSearchQuery query) {
        try {
            // 1. 创建搜索请求
            SearchRequest searchRequest = new SearchRequest(NovelIndexInitializer.INDEX_NAME);
            searchRequest.types(NovelIndexInitializer.TYPE_NAME); // 6.x需要指定type

            // 2. 构建查询条件
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 关键词搜索（多字段匹配，带权重）
            if (query.getKeyword() != null && !query.getKeyword().isEmpty()) {
                boolQuery.should(QueryBuilders.matchQuery("bookTitle", query.getKeyword())
                                .analyzer("ik_max_word_analyzer")
                                .fuzziness(Fuzziness.AUTO)) // 模糊匹配
                        .should(QueryBuilders.matchQuery("authorName", query.getKeyword())
                                .analyzer("ik_max_word_analyzer"))
                        .should(QueryBuilders.matchQuery("categoryName", query.getKeyword())
                                .analyzer("ik_max_word_analyzer"))
                        .should(QueryBuilders.matchQuery("introduction", query.getKeyword())
                                .analyzer("ik_max_word_analyzer"));
            }

            sourceBuilder.query(boolQuery);

            // 3. 分页处理
            sourceBuilder.from(query.getStartIndex());
            sourceBuilder.size(query.getPageSize());
            // 4. 排序处理（可选）
            if (query.getSortField() != null && !query.getSortField().isEmpty()) {
                SortOrder order = "desc".equalsIgnoreCase(query.getSortDirection()) 
                    ? SortOrder.DESC : SortOrder.ASC;
                sourceBuilder.sort(query.getSortField(), order);
            } else {
                // 默认按更新时间降序
                sourceBuilder.sort("updateTime", SortOrder.DESC);
            }
            searchRequest.source(sourceBuilder);

            // 5. 执行搜索
            SearchResponse response = esClient.search(searchRequest, RequestOptions.DEFAULT);

            // 6. 处理结果
            List<NovelEsDTO> resultList = new ArrayList<>();
            for (SearchHit hit : response.getHits().getHits()) {
                Map<String, Object> sourceMap = hit.getSourceAsMap();
                NovelEsDTO dto = JSON.parseObject(JSON.toJSONString(sourceMap), NovelEsDTO.class);
                resultList.add(dto);
            }

            return Result.success(resultList);
        } catch (IOException e) {
            return Result.error("搜索失败：" + e.getMessage());
        }
    }
}